package com.ruoyi.pay.refund.zfb.util;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import com.alipay.easysdk.kernel.util.ResponseChecker;
import com.alipay.easysdk.payment.common.models.AlipayTradeRefundResponse;
import com.ruoyi.common.utils.check.CheckEmptyUtil;
import com.ruoyi.config.mapper.ZfbpayConfigMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @author 🤙🤙🏼🤙🏽
 * @date 2025 4月 16 12:29
 * @Description
 */
@Slf4j
@Component
public class ZFBRefundUtil {
    @Resource
    private ZfbpayConfigMapper zfbpayConfigMapper;

    /**
     * 可选：AES密钥（接口内容加密方式），调用AES加解密相关接口时需要
     */
    private String encryptKey = "cAikHtKWeTYvCvw==";

    /**
     * 必填：协议类型：http | https 二选一
     */
    private String protocol = "https";

    /**
     * 必填：gatewayHost，默认：openapi.alipay.com
     */
    private String gatewayHost = "openapi.alipay.com";

    /**
     * 必填：签名类型，默认RSA2
     */
    private String signType = "RSA2";

    public Config getOptions(String notifyUrl) {
        Config config = new Config();
        String appId = zfbpayConfigMapper.selectOneData("AppId");
        String appPrivateKey = zfbpayConfigMapper.selectOneData("AppPrivateKey");
        String publicKey = zfbpayConfigMapper.selectOneData("PublicKey");
        String merchantCertPath = zfbpayConfigMapper.selectOneData("merchantCertPath");
        String alipayCertPath = zfbpayConfigMapper.selectOneData("alipayCertPath");
        String alipayRootCertPath = zfbpayConfigMapper.selectOneData("alipayRootCertPath");
        String zfbModel = zfbpayConfigMapper.selectOneData("zfb_model");
        config.protocol = protocol;
        config.gatewayHost = gatewayHost;
        config.signType = signType;
        config.appId = appId;
        config.notifyUrl = notifyUrl;
        config.merchantPrivateKey = appPrivateKey;
        //证书非必填
        if (Integer.parseInt(zfbModel) == 2){
            config.merchantCertPath = merchantCertPath;
            config.alipayCertPath = alipayCertPath;
            config.alipayRootCertPath = alipayRootCertPath;
        }else if (Integer.parseInt(zfbModel) == 1){
            //注：如果采用非证书模式，则无需赋值上面的三个证书路径，改为赋值如下的支付宝公钥字符串即可
            config.alipayPublicKey = publicKey;
        } else {
            throw new RuntimeException("配置信息有误：证书模式配置不完整或未配置公钥模式，请检查！");
        }
        //可设置AES密钥，调用AES加解密相关接口时需要（可选）
        config.encryptKey = encryptKey;
        return config;
    }


    /**
     * 退款接口（支持部分退款）
     *
     * @param tradeNo      特殊可选：商户订单号
     * @param outTradeNo   特殊可选：商户订单号
     * @param refundAmount 必填：退款金额
     * @param reason       可选：退款原因
     * @apiNote tradeNo 和 outTradeNo 不能同时为空。同时存在优先取 tradeNo。
     */
    public AlipayTradeRefundResponse refund(String tradeNo, String outTradeNo, String refundAmount, String reason) throws Exception {
        // 校验参数
        if (CheckEmptyUtil.isEmpty(tradeNo) && CheckEmptyUtil.isEmpty(outTradeNo)) {
            throw new RuntimeException("参数错误");
        }
        // 设置参数
        Factory.setOptions(this.getOptions(null));
        // 生成唯一的款请求号
        String outRequestNo = IdUtil.simpleUUID();
        // 发起请求
        AlipayTradeRefundResponse response = Factory.Payment.Common()
                // 支付宝交易号
                .optional("out_trade_no", tradeNo)
                // 退款原因
                .optional("refund_reason", reason)
                // 退款请求号
                .optional("out_request_no", outRequestNo)
                // 执行退款
                .refund(outTradeNo, refundAmount);
        log.info("支付宝退款结果:{}", JSON.toJSONString(response));
        // 如果请求成功（即返回信息中没有sub_code）
        if (ResponseChecker.success(response)) {
            return response;
        } else {
            throw new RuntimeException("支付宝退款失败:"+response.msg);
        }

    }

}
